package com.wb.server.tcp.server;

import com.wb.server.processor.DataProcessorFactory;
import com.wb.server.tcp.server.handler.ServerHandler;
import com.wb.server.tcp.server.handler.Unpack104Handler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author cy
 * @date 2022/4/15
 **/
@Slf4j
public class TcpIecServer extends AbstractIecServer{

    public TcpIecServer(DataProcessorFactory dataProcessorFactory) {
        this.dataProcessorFactory = dataProcessorFactory;
    }

    @Override
    public void startServer(int port) {
        //linux
        //EpollEventLoopGroup boos = new EpollEventLoopGroup(1);
        //EpollEventLoopGroup worker = new EpollEventLoopGroup();
        //windows
        NioEventLoopGroup boos=new NioEventLoopGroup(1);
        NioEventLoopGroup worker=new NioEventLoopGroup();

        ServerBootstrap bootstrap = new ServerBootstrap();

        try {
            //Linux  使用 EpollServerSocketChannel 提升效率  Windows使用NioServerSocketChannel  二选一
            //bootstrap.group(boos, worker).channel(EpollServerSocketChannel.class)
                    bootstrap.group(boos, worker).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 沾包拆包工具
                            pipeline.addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS));
                            pipeline.addLast("unpack", new Unpack104Handler());
                            pipeline.addLast(new ServerHandler(dataProcessorFactory));
                        }
                    });
            ChannelFuture future = bootstrap.bind(port).sync();
            log.info("Collect server is start on port: {}(TCP).", port);
            Channel channel = future.channel();
            channel.closeFuture().sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                boos.shutdownGracefully().sync();
                worker.shutdownGracefully().sync();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

